package com.seo.service.lightpay.impl;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alipay.api.AlipayConstants;
import com.github.pagehelper.PageInfo;
import com.seo.function.PageTool;
import com.seo.mapper.lightpay.LightPayAlipayMapper;
import com.seo.mapper.lightpay.LightPayMapper;
import com.seo.mapper.user.ConfigMapper;
import com.seo.mapper.user.UserMapper;
import com.seo.pojo.ReturnBody;
import com.seo.pojo.lightpay.LightPayCashier;
import com.seo.service.business.impl.BusinessServiceImpl;
import com.seo.service.lightpay.sdk.LightPayAlipayService;
import com.seo.service.lightpay.sdk.LightPayProxyService;
import com.seo.service.user.sdk.UserDomainService;
import com.seo.utils.ClientConst;
import com.seo.utils.DataUtil;
import com.seo.utils.DateUtil;
import com.seo.utils.Jurisdiction;
import com.seo.utils.alipay.AlipayConfig;
import com.seo.utils.alipay.AlipayUtil;
import com.seo.utils.alipay.LightPayCashierAlipay;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service("lightPayAlipayService")
public class LightPayAlipayServiceImpl implements LightPayProxyService, LightPayAlipayService {

	@Autowired
	private LightPayServiceImpl lightPayService;

	@Autowired
	private LightPayMapper lightPayMapper;

	@Autowired
	private UserMapper userMapper;

	@Autowired
	private LightPayAlipayMapper lightPayAlipayMapper;

	@Autowired
	private BusinessServiceImpl businessService;

	@Autowired
	private AlipayUtil alipayUtil;

	@Autowired
	private PageTool pageTool;

	@Autowired
	private ConfigMapper configMapper;

	@Autowired
	private UserDomainService userDomainService;

	@PostConstruct
	public void init() {
		log.info("支付宝支付-注册-开始");
		lightPayService.put("alipay", this);
		log.info("支付宝支付-注册-结束");
	}

	@Override
	public ReturnBody getAlipayConfigList(Map<String, Object> params) {
		ReturnBody body = ReturnBody.init();

		PageInfo<AlipayConfig> page = pageTool.getAutoPage(lightPayAlipayMapper::getAlipayConfigList, params);
		body.put("page", page);
		return body.success();
	}

	@Override
	public ReturnBody getCheckParams(String tradeId, LightPayCashier lpc) {

		ReturnBody body = ReturnBody.init();
		if (!LightPayCashierAlipay.AlipayType.isExists(lpc.getPayType())) {
			log.error("[{}]-【支付宝支付-支付类型不存在】", tradeId);
			return body.error("请选择支付类型");
		}

		return body.success();
	}

	@Override
	public ReturnBody saveLightPayCashier(String tradeId, LightPayCashier lpc) {
		log.info("[{}]-【支付宝支付】-【交易流水号：{}】-【用户：{}】-【开始】", tradeId, lpc.getTransactionCode(), lpc.getUserId());
		ReturnBody body = ReturnBody.init();
		try {
			log.info("[{}]-【支付宝支付】-【支付类型:{}】", tradeId, lpc.getPayType());
			AlipayConfig ac = getAlipayConfig(lpc);
			if (ac == null) {
				log.error("[{}]-【支付宝配置[{}]不存在】", tradeId, lpc.getPayType());
				return body.rollback("暂未开通支付宝支付");
			}
			log.info("[{}]-【支付宝配置信息[{}]】", tradeId, ac);

			String totalAmount = null;

			if (LightPayCashier.PayValue.test.equals(ac.getPayValue())) {
				totalAmount = ac.getTotalAmount();
			} else {
				totalAmount = lpc.getAmount().setScale(2, BigDecimal.ROUND_DOWN).toString();
			}
			log.info("[{}]-【支付宝支付】-【封装支付宝参数】", tradeId);

			Integer parentUserId = 0;
			if (lpc.getOtherParams().containsKey("parentUserId")) {
				parentUserId = (Integer) (lpc.getOtherParams().get("parentUserId"));
			}
			StringBuffer notifyUrl = new StringBuffer();
			notifyUrl.append(ac.getDomain()).append(ac.getNotifyUrl()).append("/").append(lpc.getPayType()).append("/")
					.append(parentUserId);

			StringBuffer returnUrl = new StringBuffer();
			returnUrl.append(Jurisdiction.getRequest().getAttribute("curDomain")).append(ac.getReturnUrl()).append("/")
					.append(lpc.getPayType()).append("/").append(parentUserId);

			Map<String, String> alipayParams = new HashMap<String, String>();
			alipayParams.put("outTradeNo", lpc.getCode());
			alipayParams.put("subject", lpc.getRemark());
			alipayParams.put("totalAmount", totalAmount);
			alipayParams.put("body", lpc.getRemark());
			alipayParams.put("appId", ac.getAppId());
			alipayParams.put("returnUrl", returnUrl.toString());
			alipayParams.put("notifyUrl", notifyUrl.toString());
			alipayParams.put("sellerId", ac.getSellerId());
			alipayParams.put("timeOutExpress", ac.getTimeOutExpress());
			alipayParams.put("alipayPublicKey", ac.getAlipayPublicKey());
			alipayParams.put("appPrivateKey", ac.getAppPrivateKey());
			alipayParams.put("charset", ac.getCharset());
			alipayParams.put("gateWayUrl", ac.getGateWayUrl());
			alipayParams.put("signType", ac.getSignType());
			String qrPayMode = (String) (lpc.getOtherParams().get("qrPayMode"));
			if (StringUtils.isNotEmpty(qrPayMode)) {
				alipayParams.put("qrPayMode", qrPayMode);
			}
			String qrcodeWidth = (String) (lpc.getOtherParams().get("qrcodeWidth"));
			if (StringUtils.isNotEmpty(qrcodeWidth)) {
				alipayParams.put("qrcodeWidth", qrcodeWidth);
			}

			String res = alipayUtil.get(lpc.getPayType()).invoke(alipayParams);
			if (StringUtils.isEmpty(res)) {
				return body.rollback("支付宝调用失败");
			}
			body.put("res", res);
			return body.success();
		} catch (Exception e) {
			log.error("[{}]-【支付宝调用异常-[{}]】", tradeId, e);
			return body.rollback("系统异常!");
		} finally {
			body.result();
			log.info("[{}]-【支付宝支付】-【结束】", tradeId);
		}

	}

	@Override
	public AlipayConfig getAlipayConfig(LightPayCashier lpc) {

		int userId = 0;
		if (lpc.getOtherParams().containsKey("parentUserId")) {
			userId = (int) (lpc.getOtherParams().get("parentUserId"));
		}
		return getAlipayConfig(lpc.getPayType(), userId);
	}

	@Override
	public AlipayConfig getAlipayConfig(String payType, int userId) {
		Map<String, Object> params = new HashMap<>();
		params.put("state", "01");
		params.put("payType", payType);

		if (userId > 0) {
			params.put("userId", userId);
		} else {
			params.put("userId", 0);
		}
		return lightPayAlipayMapper.getAlipayConfig(params);
	}

	@Override
	public <T> ReturnBody updateLightPayCashier(String tradeId, T t) {
		ReturnBody rb = ReturnBody.init();
		LightPayCashierAlipay result = (LightPayCashierAlipay) t;

		String tradeStatus = result.getTradeStatus();
		String code = result.getOutTradeNo();
		log.info("[{}]-【支付宝回调】-【收银流水号：{}】-【开始】", tradeId, code);
		// 查询收银记录
		LightPayCashier lpc = lightPayMapper.getLightpayCashierByCode(code);
		if (lpc == null) {
			log.error("[{}]-【支付宝-收银记录不存在】", tradeId);
			return rb.rollback();
		}

		if (lpc != null && LightPayCashier.State.no.equals(lpc.getState())) {
			LightPayCashierAlipay lpca = new LightPayCashierAlipay();
			BigDecimal totalAmount = DataUtil.getBigDecimal(result.getTotalAmount());

			AlipayConfig ac = result.getAc();
			if (LightPayCashier.PayValue.test.equals(ac.getPayValue())) {
				lpca.setTotalAmount(ac.getTotalAmount());
			} else {
				lpca.setTotalAmount(lpc.getAmount().toString());
			}

			if (DataUtil.getBigDecimal(lpca.getTotalAmount()).compareTo(totalAmount) == 0) {
				log.info("[{}]-【支付宝回调】-【保存收银记录】", tradeId, code);
				String curTime = DateUtil.getTime();
				lpca.setAppId(result.getAppId());
				lpca.setCashierId(lpc.getId());
				lpca.setTradeNo(result.getTradeNo());
				lpca.setTotalAmount(result.getTotalAmount());
				lpca.setSellerId(result.getSellerId());
				lpca.setBuyerId(result.getBuyerId());
				lpca.setTradeStatus(tradeStatus);
				lpca.setRefundFee(result.getRefundFee());
				lpca.setGmtCreate(result.getGmtCreate());
				lpca.setGmtPayment(result.getGmtPayment());
				lpca.setGmtRefund(result.getGmtRefund());
				lpca.setGmtClose(result.getGmtClose());
				lpca.setTimeStart(result.getGmtCreate());
				lpca.setTimeEnd(curTime);
				if (StringUtils.equals(tradeStatus, LightPayCashierAlipay.TRADE_SUCCESS)
						|| StringUtils.equals(tradeStatus, LightPayCashierAlipay.TRADE_FINISHED)) {
					lpc.setPayMode(LightPayCashier.PayMode.alipay.getValue());
					lpc.setState(LightPayCashier.State.finish.getValue());
				} else {
					lpc.setState(LightPayCashier.State.faile.getValue());
				}
				lpc.setFinishTime(curTime);
				int num = lightPayMapper.updateLightpayStateById(lpc);
				if (num == 1) {
					num = lightPayAlipayMapper.saveLightpayCashierAlipay(lpca);
				}
				if (num == 0) {
					log.error("[{}]-【更新收银记录失败】", tradeId);
					return rb.rollback();
				}
				if (num == 1 && LightPayCashier.State.finish.equals(lpc.getState())) {
					// 处理业务
					Map<String, Object> params = new HashMap<>();
					params.put("transactionCode", lpc.getTransactionCode());
					params.put("payType", lpc.getPayType());
					params.put("payMode", lpc.getPayMode());
					rb.run(businessService.updatePayBusiness(tradeId, params));
					if (!rb.isSuccess()) {
						return rb.rollback(false, true);
					}
					return rb.success();
				}

			}
		}

		return rb.rollback();
	}

	@Override
	public ReturnBody save(AlipayConfig ac, String type) {
		ReturnBody rb = ReturnBody.init();
		if (StringUtils.isEmpty(ac.getAppId())) {
			log.error("请填写app_id");
			return rb.error("请填写app_id");
		}
		if (StringUtils.isEmpty(ac.getSellerId())) {
			log.error("请填写商户ID");
			return rb.error("请填写商户ID");
		}
		if (StringUtils.isEmpty(ac.getEncryptKey())) {
			log.error("请填写AES秘钥");
			return rb.error("请填写AES秘钥");
		}

		if (StringUtils.isEmpty(ac.getAppPrivateKey())) {
			log.error("请填写私钥");
			return rb.error("请填写私钥");
		}
		if (StringUtils.isEmpty(ac.getAlipayPublicKey())) {
			log.error("请填写支付宝公钥");
			return rb.error("请填写支付宝公钥");
		}
		if (StringUtils.isEmpty(ac.getPayType())) {
			log.error("请选择支付类型");
			return rb.error("请选择支付类型");
		}

		if (ac.isInsert()) {
			log.info("添加支付宝配置");
			if (StringUtils.isEmpty(ac.getUserName())) {
				log.error("请输入用户名");
				return rb.error("请输入用户名");
			}
			Map<String, Object> user = userMapper.getUserByUserName(ac.getUserName());
			if (user == null) {
				log.error("请输入用户名");
				return rb.error("请输入用户名");
			}
			ac.setUserId((Integer) user.get("id"));
		} else {
			log.info("更新支付宝配置");
			if (ac.getId() <= 0) {
				log.error("请选择支付宝配置");
				return rb.error("请选择支付宝配置");
			}
		}

		if ("proxy".equals(type)) {
			Integer userId = Jurisdiction.getT("id", Integer.class, ClientConst.SESSION_USER);
			if (!userId.equals(ac.getUserId())) {
				Map<String, Object> childUser = userMapper.getUserById(ac.getUserId());
				Integer parentId = (Integer) childUser.get("parentId");
				if (!parentId.equals(userId)) {
					log.error("请选择自己或下级用户");
					return rb.error("请选择自己或下级用户");
				}
			}
		}
		String domain = userDomainService.getDefaultDomain();
		String port = configMapper.getConfig("seo-port");
		ac.setSignType(AlipayConstants.SIGN_TYPE_RSA2);
		ac.setGateWayUrl(AlipayConfig.DEFAULT_GATEWAYURL);
		ac.setEncryptType(AlipayConstants.ENCRYPT_TYPE_AES);
		ac.setDomain("http://" + domain + ((!"80".equals(port) && StringUtils.isNoneEmpty(port)) ? (":" + port) : ""));
		ac.setReturnUrl(AlipayConfig.DEFAULT_RETURN_URL);
		ac.setNotifyUrl(AlipayConfig.DEFAULT_NOTIFY_URL);
		ac.setTimeOutExpress(AlipayConfig.DEFAULT_TIME_OUT_EXPRESS);
		int num;
		if (ac.isInsert()) {
			num = lightPayAlipayMapper.saveAlipayConfig(ac);
		} else {
			num = lightPayAlipayMapper.updateAlipayConfig(ac);
		}
		if (num == 0) {
			log.error("保存支付宝配置失败");
			return rb.error("保存支付宝配置失败");
		}

		return rb.success();
	}

	@Override
	public ReturnBody updateState(Integer id, String state) {
		ReturnBody rb = ReturnBody.init();
		if (id <= 0) {
			log.error("请选择支付宝配置");
			return rb.error("请选择支付宝配置");
		}
		if (StringUtils.isEmpty(state)) {
			log.error("状态异常");
			return rb.error("参数错误");
		}

		AlipayConfig ac = new AlipayConfig();
		ac.setId(id);
		ac.setState(state);
		int num = lightPayAlipayMapper.updateAlipayConfig(ac);
		if (num == 0) {
			log.error("保存支付宝配置失败");
			return rb.error("保存支付宝配置失败");
		}
		return rb.success();
	}

}
